#include "SampleClient.h"
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <iomanip>

void 
SampleClient::onLogin() 
{
    std::cout << "Login successful." << std::endl ;
    //
    // Request a list of exchanges that can be accessed by the current
    // user. The onListExchanges() method will be called when this is received
    // from the server. We ignore the request_id returned by this method
    // in this sample code.
    //
    const int request_id = this->requestListExchanges() ;
#if 0   
    //
    // Request the real-time tick stream for symbol GOOG from NASDAQ NMS exchange
    // (exchange code "Q"). This sample assumes that the user has subscription
    // to this exchange.
    //
    OTDataEntity csco_data = OTDataEntity ("Q", "GOOG") ;
    id = requestTickStream ( &csco_data );
             
    struct tm begDate = { 0, 0,  9, 15, 11, 104 };
    struct tm endDate = { 0, 0, 15, 25, 11, 104 };
                                         
    OTDataEntity msft_data = OTDataEntity ("Q", "MSFT") ; 
    requestHistData ( &msft_data,
                      mktime(&begDate),
                      mktime(&endDate),
                      OT_HIST_OHLC_TICK_BASED,
                      1 ) ;
#endif                      
    return ;
}

void 
SampleClient::onError(OTError* otError) 
{
    std::ostringstream error_message ;
    error_message << __FILE__ << ":" << __LINE__ << ": " 
                  << "OTFeed Error encountered."
                  << std::endl 
                  << "Error Id:   " << otError->getRequestId() 
                  << std::endl 
                  << "Error Code: " << otError->getCode() 
                  << std::endl 
                  << "Description: " << otError->getDescription() 
                  << std::endl ;
    std::cerr << error_message.str() ;
    throw std::runtime_error( error_message.str() ) ;
}

void 
SampleClient::onListExchanges( OTExchange* exchangeList, 
                               int         numOfExchanges ) 
{
    //
    // Do not do anything if the exchangeList is NULL. 
    //
    if ( 0 == exchangeList )
    {
        return ;
    }
    //
    std::cout << __FILE__ << ":" << __LINE__ << ": "
              << "List of supported exchanges: (total "
              << numOfExchanges << "):" 
              << std::endl ; 
    std::cout << std::setw(80)
              << std::setfill('-')
              << ""
              << std::setfill(' ')
              << std::endl ;
    std::cout << std::setw(60)
              << std::left
              << "Title"
              << std::setw(8)
              << "Code"
              << std::setw(10)
              << "Available"
              << std::endl ;     
    std::cout << std::setw(80)
              << std::setfill('-')
              << ""
              << std::setfill(' ')
              << std::endl ;
    for(int i=0; i<numOfExchanges; ++i)
    {
        std::cout << std::setw(60)
                  << std::left
                  << exchangeList[i].getTitle() 
                  << std::setw(8)
                  << exchangeList[i].getCode()
                  << std::setw(10)
                  << ( ( exchangeList[i].getAvailable() ) ?
                       "Yes" : "No " ) 
                  << std::endl ;
    }   
    std::cout << std::setw(80)
              << std::setfill('-')
              << ""
              << std::setfill(' ')
              << std::endl ;                 

#if 0          
    bool first = false;
    for (int i = 0; i < exchangeNum; i++)
    {
        std::cout << __FILE__ << ":" << __LINE__ << ": "
                  << "Exchange num = "
                  << (i+1)
                  << " ==============================>"
                  << std::endl ;
        if( !first )
        {
            std::cout << "requestID = " 
                      << listExchange[i].getRequestId()
                      << std::endl ;
            std::cout << "URL = "
                      << listExchange[i].getSubscriptionURL()
                      << std::endl ;
            first = true;
        }

        std::cout << "     available = " 
                  << listExchange[i].getAvailable()
                  << std::endl ;
        std::cout << " exchange code = "
                  << listExchange[i].getCode()
                  << std::endl ;
        std::cout << " exchange title = "
                  << listExchange[i].getTitle()
                  << std::endl ;
        std::cout << " exchange desc = "
                  << listExchange[i].getDescription()
                  << std::endl ;
        return ;
    }
#endif    
}

void SampleClient::onTodaysOHL(int requestId, double openPrice, double highPrice, double lowPrice)
{
    printf ("reqId = %d, openPrice =%f, highPrice = %f, lowPrice = %f\n", requestId, openPrice, highPrice, lowPrice);
}

void SampleClient::onMessage (OTMessage *message) 
{
    printf ("msgCode=%d msg=%s\n", message->getCode(),message->getDescription());     
}

void SampleClient::onRealtimeQuote (OTQuote *quote)
{
    printf ("RealTimeQuote: id = %d, timestamp = %d , askPrice = %f, bidPrice = %f, askSize = %d, bidSize = %d, \
               askExchange = %s , indicator = %c, tickIndicator = %c \n", quote->getRequestId(), quote->getTimestamp(),
            quote->getAskPrice(), quote->getBidPrice(), quote->getAskSize(), quote->getBidSize(), quote->getAskExchange(),
            quote->getIndicator(), quote->getTickIndicator()
        );
      
    if (quote->getSymbol())
    {
        printf ("symbol= %s\n", quote->getSymbol());
    }
}

void SampleClient::onRealtimeMMQuote (OTMMQuote * mmQuote)
{
    printf ("RealTimeMMQuote: id = %d, timestamp = %d, askPrice = %f, bidPrice = %f, askSize = %d, bidSize = %d, \
               mmid = %s, indicator = %c \n", mmQuote->getRequestId(), mmQuote->getTimestamp(), mmQuote->getAskPrice(),
            mmQuote->getBidPrice(), mmQuote->getAskSize(), mmQuote->getBidSize(), mmQuote->getMMID(), 
            mmQuote->getIndicator()
        );

    if (mmQuote->getSymbol())
    {
        printf ("symbol= %s\n", mmQuote->getSymbol());
    }
}

void SampleClient::onRealtimeTrade (OTTrade *trade)
{
    printf ("RealTimeTrade: id = %d, timestamp = %d, price = %f, size = %d, volume = %lld ",
            trade->getRequestId(), trade->getTimestamp(), trade->getPrice(), trade->getSize(), trade->getVolume()
        );
                                  
    printf ("sequenceNumber = %d, indicator = %c, tickIndicator = %c, isOpen = %d, isHigh = %d, isLow = %d, isClose = %d, isUpdateLast = %d \
              isUpdateVolume = %d, isCancel = %d, isFromBook = %d \n", trade->getSequenceNumber(), trade->getIndicator(), trade->getTickIndicator(),
            trade->isOpen(), trade->isHigh(), trade->isLow(), trade->isClose(), 
            trade->isUpdateLast(), trade->isUpdateVolume(), trade->isCancel(), trade->isFromBook()
        );

    if (trade->getSymbol())
    {
        printf ("symbol= %s\n", trade->getSymbol());
    }
}
    
void SampleClient::onHistQuote (OTQuote *quote)
{
    printf ("HistQuote: id = %d, timestamp = %d , askPrice = %f, bidPrice = %f, askSize = %d, bidSize = %d, \
               askExchange = %s , indicator = %c, tickIndicator = %c \n", quote->getRequestId(), quote->getTimestamp(),
            quote->getAskPrice(), quote->getBidPrice(), quote->getAskSize(), quote->getBidSize(), quote->getAskExchange(),
            quote->getIndicator(), quote->getTickIndicator()
        );         
}  

void SampleClient::onHistMMQuote (OTMMQuote *mmQuote)
{
      
    printf ("HistMMQuote: id = %d, timestamp = %d, askPrice = %f, bidPrice = %f, askSize = %d, bidSize = %d, \
               mmid = %4s, indicator = %c \n", mmQuote->getRequestId(), mmQuote->getTimestamp(), mmQuote->getAskPrice(),
            mmQuote->getBidPrice(), mmQuote->getAskSize(), mmQuote->getBidSize(), mmQuote->getMMID(), 
            mmQuote->getIndicator()
        );
}

void SampleClient::onHistTrade (OTTrade *trade)
{
    printf ("HistTrade: id = %d, timestamp = %d, price = %f, size = %d, volume = %lld ",
            trade->getRequestId(), trade->getTimestamp(), trade->getPrice(), trade->getSize(), trade->getVolume()
        );
                                  
    printf ("sequenceNumber = %d, indicator = %c, tickIndicator = %c, isOpen = %d, isHigh = %d, isLow = %d, isClose = %d, isUpdateLast = %d \
              isUpdateVolume = %d, isCancel = %d, isFromBook = %d \n", trade->getSequenceNumber(), trade->getIndicator(), trade->getTickIndicator(),
            trade->isOpen(), trade->isHigh(), trade->isLow(), trade->isClose(), 
            trade->isUpdateLast(), trade->isUpdateVolume(), trade->isCancel(), trade->isFromBook()
        );
}

void SampleClient::onHistOHLC (OTOHLC *data)
{
    printf ("OHLC id=%-2d timestamp = %d O=$%.2f H=$%.2f L=$%.2f C=$%.2f volume=%lld\n",data->getRequestId(), data->getTimestamp(),data->getOpenPrice(), data->getHighPrice(),               
            data->getLowPrice(), data->getClosePrice(), data->getVolume());
}
   
void SampleClient::onRestoreConnection () 
{
    printf ("onRestoreConnection\n");
}

void SampleClient::onStatusChanged (int status)
{
    printf("onStatusChanged - new status %d \n", status);
}

void SampleClient::onEquityInit (OTEquityInit *equityInit)
{
    printf ("onEquityInit = \n");

    printf ("reqId = %d, instumentType = %d, currency = %s, companyName =%s, cusip = %s, isin = %s, ",              
            equityInit->getRequestId(),  equityInit->getInstrumentType(),
            equityInit->getCurrency(),   equityInit->getCompanyName(),
            equityInit->getCUSIP(),      equityInit->getISIN());

    printf ("prevCloseDate =%s, prevClosePrice =%f, annualHighDate =%s, annualHighPrice =%f,",
            equityInit->getPrevCloseDate(), equityInit->getPrevClosePrice(),
            equityInit->getAnnualHighDate(), equityInit->getAnnualHighPrice());


    printf ("annualLowDate =%s, annualLowPrice =%f, earningsDate =%s, earningsPrice =%f,",
            equityInit->getAnnualLowDate(),   equityInit->getAnnualLowPrice(),
            equityInit->getEarningsDate(),    equityInit->getEarningsPrice());
      
    printf ("totalShares =%lld, averageVolume =%lld, isUPC11830 =%d, isSmallCap =%d, isTestlssue =%d\n",
            equityInit->getTotalShares(),    equityInit->getAverageVolume(),
            equityInit->isUPC11830(),     equityInit->isSmallCap(),
            equityInit->isTestlssue());

}

void SampleClient::onBookCancel (OTBookCancel *bookCancel)
{
    printf ("onBookCancel\n");
    printf ("Id =%2d, timestamp = %d, orderRef = %s, size =%d\n", bookCancel->getRequestId(), bookCancel->getTimestamp(),
            bookCancel->getOrderRef(), bookCancel->getSize());
}
    
void SampleClient::onBookChange (OTBookChange *bookChange)
{
    printf ("onBookChange\n");
    printf ("Id =%2d, timestamp = %d, orderRef = %s, size =%d price =%f \n", bookChange->getRequestId(), bookChange->getTimestamp(),
            bookChange->getOrderRef(), bookChange->getSize(), bookChange->getPrice());
}
    
void SampleClient::onBookDelete (OTBookDelete *bookDelete)
{
    printf ("onBookDelete\n");
    printf ("Id =%2d, timestamp = %d, orderRef = %s, sideIndicator =%c  deleteType =%c \n", bookDelete->getRequestId(), 
            bookDelete->getTimestamp(), bookDelete->getOrderRef(), bookDelete->getSide(), bookDelete->getDeleteType());
}
    
void SampleClient::onBookExecute (OTBookExecute *bookExecute)
{
    printf ("onBookExecute\n");
    printf ("Id =%2d, timestamp = %d, orderRef = %s, size =%d  matchNumber =%d \n", bookExecute->getRequestId(), 
            bookExecute->getTimestamp(), bookExecute->getOrderRef(), bookExecute->getSize(), bookExecute->getMatchNumber());
}
    
void SampleClient::onBookOrder (OTBookOrder *bookOrder)
{
    printf ("onBookOrder\n");
    printf ("Id =%2d, timestamp = %d, orderRef = %s, size =%d  sideIndicator =%c, display = %d, price = %f \n", 
            bookOrder->getRequestId(), bookOrder->getTimestamp(), bookOrder->getOrderRef(), bookOrder->getSize(), 
            bookOrder->getSide(), bookOrder->getDisplay(), bookOrder->getPrice());
}
    
    
void SampleClient::onBookPriceLevel (OTBookPriceLevel *bookPriceLevel)
{
    printf ("onBookPriceLevel\n");
    printf ("Id =%2d, timestamp = %d, size =%d  sideIndicator =%c, levelId = %s, price = %f \n", 
            bookPriceLevel->getRequestId(), bookPriceLevel->getTimestamp(), bookPriceLevel->getSize(), 
            bookPriceLevel->getSide(), bookPriceLevel->getLevelId(), bookPriceLevel->getPrice());
}
    
void SampleClient::onBookPurge (OTBookPurge *bookPurge)
{
    printf ("onBookPurge\n");
    printf ("Id =%2d, timestamp = %d, exchangeNameBase = %s\n", bookPurge->getRequestId(), 
            bookPurge->getTimestamp(), bookPurge->getExchangeNameRoot());
}
    
void SampleClient::onBookReplace (OTBookReplace *bookReplace)
{
    printf ("onBookReplace\n");
    printf ("Id =%2d, timestamp = %d, orderRef = %s, size =%d,  sideIndicator =%c, price = %f \n", bookReplace->getRequestId(), 
            bookReplace->getTimestamp(), bookReplace->getOrderRef(), bookReplace->getSize(), bookReplace->getSide(),
            bookReplace->getPrice());
}
   
void SampleClient::onRealtimeBBO (OTBBO *bbo)
{
    printf ("onRealtimeBBO\n");
    printf ("Id =%2d, timestamp = %d,  size =%d,  side =%c, price = %f symbol =%s \n", bbo->getRequestId(), 
            bbo->getTimestamp(), bbo->getSize(), bbo->getSide(), bbo->getPrice(), bbo->getSymbol());
   
}
